package com.pro.common.modules.service.dependencies.upload.test;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MinioUploadHttpUtil {

    public static void main(String[] args) {
        String minioEndpoint = "http://127.0.0.1:9000"; // MinIO 服务器地址
        String bucketName = "baoyi";
        String objectName = "1_upload.png"; // 存储在 MinIO 中的文件名
        String filePath = "C:\\1.png"; // 本地文件路径
        String accessKey = "minioadmin"; // 访问密钥
        String secretKey = "minioadmin"; // 密钥

        try (FileInputStream fileInputStream = new FileInputStream(filePath)) {
            uploadFile(minioEndpoint, bucketName, objectName, accessKey, secretKey, fileInputStream, new File(filePath).length());
            System.out.println("文件上传成功！");
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("文件上传失败：" + e.getMessage());
        }
    }

    public static void uploadFile(String endpoint, String bucketName, String objectName, String accessKey, String secretKey,
                                  InputStream fileInputStream, long fileLength) throws IOException {
        // 获取当前日期，用于签名
        String date = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'").format(new Date());
        String region = "us-east-1"; // MinIO 使用的区域
        String service = "s3"; // 服务名称

        // 生成签名密钥
        String signingKey = getSigningKey(secretKey, date, region, service);

        // 计算请求 URL 和方法
        String uploadUrl = endpoint + "/" + bucketName + "/" + objectName;

        // 创建 URL 和连接
        URL url = new URL(uploadUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置 HTTP 方法为 PUT，上传文件
        connection.setRequestMethod("PUT");
        connection.setDoOutput(true);

        // 设置请求的内容类型为文件
        connection.setRequestProperty("Content-Type", "application/octet-stream");
        connection.setRequestProperty("x-amz-date", date); // 设置 x-amz-date
        connection.setRequestProperty("Authorization", "AWS4-HMAC-SHA256 Credential=" + accessKey + "/" + date + "/" + region + "/" + service + "/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=" + signingKey);

        // 设置请求的内容长度
        connection.setRequestProperty("Content-Length", String.valueOf(fileLength));

        // 写入文件流到输出流
        try (OutputStream out = connection.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }
        }

        // 执行请求并获得响应
        int responseCode = connection.getResponseCode();
        if (responseCode != HttpURLConnection.HTTP_OK) {
            // 如果响应码不是 200，读取错误流并输出
            InputStream errorStream = connection.getErrorStream();
            StringBuilder errorResponse = new StringBuilder();
            int byteRead;
            while ((byteRead = errorStream.read()) != -1) {
                errorResponse.append((char) byteRead);
            }
            throw new IOException("上传文件失败，响应码: " + responseCode + ", 错误信息: " + errorResponse.toString());
        }
    }

    private static String getSigningKey(String secretKey, String date, String region, String service) throws IOException {
        byte[] kDate = hmacSha256(("AWS4" + secretKey).getBytes(StandardCharsets.UTF_8), date); // 签名密钥: "AWS4" + secretKey
        byte[] kRegion = hmacSha256(kDate, region); // 签名密钥 + region
        byte[] kService = hmacSha256(kRegion, service); // 签名密钥 + service
        return new String(hmacSha256(kService, "aws4_request"), StandardCharsets.UTF_8); // 最后拼接 "aws4_request"
    }

    private static byte[] hmacSha256(byte[] key, String value) throws IOException {
        try {
            javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA256");
            javax.crypto.spec.SecretKeySpec keySpec = new javax.crypto.spec.SecretKeySpec(key, "HmacSHA256");
            mac.init(keySpec);
            return mac.doFinal(value.getBytes(StandardCharsets.UTF_8));
        } catch (Exception e) {
            throw new IOException("HMAC SHA256 计算失败", e);
        }
    }
}
